/*
 * COPYRIGHT. ShenZhen JiMi Technology Co., Ltd. 2017.
 * ALL RIGHTS RESERVED.
 *
 * No part of this publication may be reproduced, stored in a retrieval system, or transmitted,
 * on any form or by any means, electronic, mechanical, photocopying, recording, 
 * or otherwise, without the prior written permission of ShenZhen JiMi Network Technology Co., Ltd.
 *
 * Amendment History:
 * 
 * Date                   By              Description
 * -------------------    -----------     -------------------------------------------
 * 2017年4月5日    li.shangzhi         Create the class
 * http://www.jimilab.com/
 */

package com.jimi.gateway.filter.openapi.pre;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.jimi.exception.ErrorCode;
import com.jimi.gateway.utils.Constants;
import com.jimi.gateway.utils.ResultModel;
import com.jimi.gateway.utils.ValidatorUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

/**
 * @FileName RequestParamFilter.java
 * @Description: 请求参数过滤器，对请求的通用参数进行校验，在PreDecorationFilter过滤器类后执行
 *
 * @Date 2017年4月5日 下午5:48:48
 * @author li.shangzhi
 * @version 1.0
 */
public class RequestParamFilter extends ZuulFilter {

	private static final int FILTER_ORDER = 6;

	private final Logger logger = LoggerFactory.getLogger(RequestParamFilter.class);

	/**
	 * 是否执行该过滤器，此处为true，说明需要过滤
	 */
	@Override
	public boolean shouldFilter() {
		RequestContext ctx = RequestContext.getCurrentContext();
		String routeId = String.valueOf(ctx.get("proxy"));
		return Constants.OPEN_API_NAMESPACE.equals(routeId);
	}

	@Override
	public Object run() {
		RequestContext ctx = RequestContext.getCurrentContext();
		ctx.getResponse().setCharacterEncoding("UTF-8");
		HttpServletRequest request = ctx.getRequest();
		logger.info("{} RequestParamFilter request to {}", request.getMethod(), request.getRequestURL().toString());

		if (!checkRequiredParams(ctx, request)) {
			ctx.setSendZuulResponse(false);// 过滤该请求，不对其进行路由
			ctx.setResponseStatusCode(200);// 返回错误码
			// ctx.setResponseBody(JSONObject.toJSONString(new
			// ResultModel(ErrorCode.PARAM_ERROR)));
			ctx.set(Constants.IS_NEXT_FILTER, false);// 后续的过滤器是否继续执行
			return null;
		}

		ctx.set(Constants.IS_NEXT_FILTER, true);// 后续的过滤器是否继续执行

		return null;
	}

	/**
	 * pre：可以在请求被路由之前调用 route：在路由请求时候被调用 post：在routing和error过滤器之后被调用
	 * error：处理请求时发生错误时被调用
	 */
	@Override
	public String filterType() {
		return Constants.PRE_FILTER;
	}

	/**
	 * 优先级为0，数字越大，优先级越低
	 */
	@Override
	public int filterOrder() {
		return FILTER_ORDER;
	}

	/**
	 * @Title: checkRequiredParams
	 * @Description: 检查api通用参数
	 * @return
	 * @author li.shangzhi
	 * @date 2017年4月5日 下午6:09:09
	 */
	private boolean checkRequiredParams(RequestContext ctx, HttpServletRequest request) {
		boolean flag = true; // 是否合法
		Map<String, String[]> paramsMap = request.getParameterMap();
		logger.info("请求的参数内容：{}", JSONObject.toJSONString(paramsMap));
		final String[] params = Constants.PARAMS;
		for (String key : params) {
			String[] values = paramsMap.get(key);
			switch (key) {
			case Constants.METHOD:
				flag = ValidatorUtils.checkMethod(ctx, values);
				break;
			case Constants.APP_KEY:
				flag = ValidatorUtils.checkAppKey(ctx, values);
				break;
			case Constants.TIMESTAMP:
				flag = ValidatorUtils.checkTimestamp(ctx, values);
				break;
			case Constants.FORMAT:
				flag = ValidatorUtils.checkFormat(ctx, values);
				break;
			case Constants.V:
				flag = ValidatorUtils.checkVersion(ctx, values);
				break;
			case Constants.SIGN_METHOD:
				flag = ValidatorUtils.checkSignMethod(ctx, values);
				break;
			case Constants.SIGN:
				String[] ver = paramsMap.get(Constants.V);
				if (Constants.VERSION_0_9.equals(ver[0])) {
					// 如果是0.9版本不校验sign值
					break;
				}
				flag = ValidatorUtils.checkSign(ctx, values);
				break;
			default:
				break;
			}
			if (!flag) {
				break;
			}
		}
		return flag;
	}

}
